﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Sodao.FastSocket.Server;
using Sodao.FastSocket.Server.Messaging;
using Sodao.FastSocket.SocketBase;
using System.Collections.Concurrent;
using ClassLibraryMessageDispacher;
using System.Collections;
using System.Threading;
namespace ClassLibraryNetCom
{
  
    public class DZ_BatteryGrandSysteamMachineNet_Manager
    {
        /// <summary>
        /// 单例实例化
        /// </summary>
        public static readonly DZ_BatteryGrandSysteamMachineNet_Manager middleMachineDevNet = new DZ_BatteryGrandSysteamMachineNet_Manager();
        private Thread threadsending = null;
        private ConcurrentQueue<MessagePackage> sending_quence = new ConcurrentQueue<MessagePackage>();
        private List<MessagePackage> saveMessagelist = new List<MessagePackage>();
        private DZ_BatteryGrandSysteamMachineNet_Manager()
        {

        }
        /// <summary>
        /// 获取所有已经连接的客户端
        /// </summary>
        /// <param name="clients"></param>
        public void GetAllClient(out string [] clients)
        {
            clients = null;
             IHost host;
            if (SocketServerManager.TryGetHost("quickStart", out host))
            {
                IConnection[] arr = host.ListAllConnection();
                clients = new string[arr.Length];
                byte ipcount = 0;
                 foreach (var c in arr)
                {
                    clients[ipcount] = c.RemoteEndPoint.Address.ToString();
                    ipcount++;             
                }
            }
        }
        public void StartServerListeningWork()
        {
            SocketServerManager.Init();
            SocketServerManager.Start();
            System.Threading.Tasks.Task.Factory.StartNew(() =>
            {
            while (true)
            {
                System.Threading.Thread.Sleep(200);
                IHost host;
                if (SocketServerManager.TryGetHost("quickStart", out host))
                {
                    IConnection[] arr = host.ListAllConnection();
                    foreach (var c in arr)
                        {
                            if (true)
                            {
                                int tcha = ((int)(DateTime.Now - c.HeartActiveTime).TotalSeconds);

                                TimeSpan seconds = new TimeSpan(DateTime.Now.Ticks - c.HeartActiveTime.Ticks);
                                if (seconds.TotalSeconds > 10) // 超过5秒没有心跳 视为客户端离线
                                {
                                   //c.BeginDisconnect();
                                }
                             
                            }
                           
                        }
                    }
                }
            });

            threadsending = new Thread(sending_thread);
            threadsending.Priority = ThreadPriority.Normal;
            threadsending.IsBackground = true;
            threadsending.Start();
            //watchClentsHeating = new Thread(watchclientHeart_thread);
            //watchClentsHeating.Priority = ThreadPriority.Normal;
            //watchClentsHeating.IsBackground = false;
            //watchClentsHeating.Start();
            Console.ReadLine();

        }
        ~DZ_BatteryGrandSysteamMachineNet_Manager()
        {
            SocketServerManager.Stop();
        }
 
        /// <summary>
        /// 处理中位机组 1-10 发来的数据
        /// </summary>
        /// <param name="connection"></param>
        /// <param name="message"></param>
        public   void Get_Complete_Message(IConnection connection,ByteDataMessage message)
        {
            Console.WriteLine("connection:" + connection.RemoteEndPoint.ToString() +" get data"/*+ glf.ToString() */+" ");
            
#if   true
            ushort squence = message.squence;
    
            if (message.direct == 0x00)
            {
                foreach (MessagePackage savemes in saveMessagelist)
                {
                    if (savemes.squence == squence && connection.RemoteEndPoint.Address.ToString() == savemes.ddinfo.destIP)
                    {

                        PushRebackMessage2MesDispacherBySaveList(savemes, message);//中位机 返回 指令包
                        saveMessagelist.Remove(savemes);
  
                        break;
                    }
                }
            }
            else if (message.direct == 0x01)
            {
                if (message.main_cmd == 0x00 && message.sub_cmd == 0x00)
                {
                    PushRebackMessageByHeats(ref connection, message);//直接组织心跳包发送
                }
                else
                {
                    PushRebackMessage2MesDispacherDricBybytesMes( ref connection, message);//中位机 上抛数据包
                }

            }
            else
            {

            }
  
#endif

        }
        /// <summary>
        /// 连接通知
        /// </summary>
        /// <param name="connection"></param>
        /// <param name="str"></param>
        public void Get_Server_Connaction_WorksNotify(IConnection connection, string str)
        {

            SoureDetailInfo sdinfo = new SoureDetailInfo();
            sdinfo.sourepath = MessagePackagePath.NetMiddleDeviceCom;
            DestDetailInfo ddinfo = new DestDetailInfo();
            ddinfo.destpath = MessagePackagePath.UICom;

            MessagePackage rebacMes = new MessagePackage(
                    ProductType.notifyevent,
                    0x01,
                    0x01,
                    false,
                    MessagePackagePath.NetMiddleDeviceCom,
                    MessagePackagePath.UICom,
                    sdinfo,
                    ddinfo,
                    str,
                     new ArraySegment<byte>(new byte[1] { 0x01 })
                    );
            if (ClassMessagerDispacher.instance.isInitInstance)
            {
                ClassMessagerDispacher.instance.PushMessageIn(ref rebacMes);
            }

        }

        private void watchclientHeart_thread(object param)
        {
            while(true)
            {
                Thread.Sleep(100);
            }
        }
            /// <summary>
            /// 直接返回心跳
            /// </summary>
            /// <param name="bytemes"></param>
        public void PushRebackMessageByHeats(ref IConnection connection, ByteDataMessage bytemes)
        {
            connection.HeartActiveTime = DateTime.Now;
            SoureDetailInfo sdinfo = new SoureDetailInfo();
            sdinfo.sourepath = MessagePackagePath.NetMiddleDeviceCom;
            DestDetailInfo ddinfo = new DestDetailInfo();
            ddinfo.destpath = MessagePackagePath.NetMiddleDeviceCom;
      
            ddinfo.destIP = connection.RemoteEndPoint.Address.ToString();

            MessagePackage rebacMes = new MessagePackage(
                   ProductType.returned,
                    bytemes.direct,
                    bytemes.squence,
                    false,
                    MessagePackagePath.NetMiddleDeviceCom,
                    MessagePackagePath.NetMiddleDeviceCom,
                    sdinfo,
                    ddinfo,
                    "heat",
                    new ArraySegment<byte>(bytemes.dataArry.ToArray())
                    );
            if (ClassMessagerDispacher.instance.isInitInstance)
            {
                ClassMessagerDispacher.instance.PushMessageIn(ref rebacMes);
            }
            Console.WriteLine( "client:"+connection.RemoteEndPoint.Address.ToString() + ":" + DateTime.Now.ToString("T") + " "+DateTime.Now.ToString("fff") + " heart beat \r\n");
        }
        /// <summary>
        ///没有找到 直接转运 视为中位机主动抛出数据
        /// </summary>
        /// <param name="savemessage"></param>
        /// <param name="bytemes"></param>
        public void PushRebackMessage2MesDispacherDricBybytesMes(ref IConnection connection, ByteDataMessage bytemes)
        {
            SoureDetailInfo sdinfo = new SoureDetailInfo();
            sdinfo.sourepath = MessagePackagePath.NetMiddleDeviceCom;
            sdinfo.soureIP = connection.RemoteEndPoint.Address.ToString();
            DestDetailInfo ddinfo = new DestDetailInfo();
            ddinfo.destpath =   MessagePackagePath.UICom;

            MessagePackage rebacMes = new MessagePackage(  
                   ProductType.updatapush,
                    bytemes.direct,
                    bytemes.squence,            
                    false,
                    MessagePackagePath.NetMiddleDeviceCom,
                    MessagePackagePath.UICom,
                    sdinfo,
                    ddinfo,
                    "out",
                   new ArraySegment<byte>(bytemes.dataArry.ToArray())
                    );
            if (ClassMessagerDispacher.instance.isInitInstance)
            {
                ClassMessagerDispacher.instance.PushMessageIn(ref rebacMes);
            }

        }

        public void PushRebackMessage2MesDispacherBySaveList( MessagePackage savemessage, ByteDataMessage bytemes)
        {
            SoureDetailInfo sdinfo = new SoureDetailInfo();
            sdinfo.sourepath = savemessage.ddinfo.destpath;

            DestDetailInfo ddinfo = new DestDetailInfo();
            ddinfo.destpath = savemessage.sdinfo.sourepath;
            ddinfo.destIP = savemessage.ddinfo.destIP;

               MessagePackage rebacMes = new MessagePackage(  
                ProductType.returned,
                savemessage.direct,
                savemessage.squence,            
                false,
                savemessage.dest,
                savemessage.soure,
                sdinfo,
                ddinfo,
                "",
                new ArraySegment<byte>( bytemes.dataArry.ToArray())
                );

            if (ClassMessagerDispacher.instance.isInitInstance)
            {
                ClassMessagerDispacher.instance.PushMessageIn(ref rebacMes);
            }

        }

        public void BeginPushMessageInSendingQuence(ref MessagePackage mes)
        {
            sending_quence.Enqueue(mes);
        }

       private void sending_thread(object param)
        {
            while(true)
            {
                Thread.Sleep(1);

                while(sending_quence.Count>0)
                {
                    Thread.Sleep(1);
                    if(sending_quence.TryDequeue(out MessagePackage outMes))
                    {

                        IHost host;
                        if (SocketServerManager.TryGetHost("quickStart", out host))
                        {
                            IConnection[] IconectionsArry_p1 = host.ListAllConnection();
                            foreach (var ic in IconectionsArry_p1)
                            {
                                if (ic.RemoteEndPoint.Address.ToString() == outMes.ddinfo.destIP)
                                {
                                    byte[] inbytes = outMes.bytesArry.Array;
                                    ic.BeginSend(ByteDataMessage.ToPacket(ref inbytes));
                                    if (outMes.isNeedReback)
                                    {
                                        saveMessagelist.Add(outMes);
                                    }
                                    Console.WriteLine(outMes.ddinfo.destIP + ":" + "sent data" + " \r\n");
                                    break;
                                }
                            }
                        }
                    }

                }

            }

        }


    }


    public class Dz_BatteryGrandSysteamService : AbsSocketService<ByteDataMessage>
    {
        public override void OnConnected(IConnection connection)
        {
            base.OnConnected(connection);
            Console.WriteLine(connection.RemoteEndPoint.ToString() + " " + connection.ConnectionID.ToString() + " connected");
            connection.BeginReceive();
            DZ_BatteryGrandSysteamMachineNet_Manager.middleMachineDevNet.Get_Server_Connaction_WorksNotify(connection, "CONE:" + connection.RemoteEndPoint.Address.ToString());
        }

        public override void OnReceived(IConnection connection, ByteDataMessage message)
        {
            base.OnReceived(connection, message);
            DZ_BatteryGrandSysteamMachineNet_Manager.middleMachineDevNet.Get_Complete_Message(connection, message);   
        }

        public override void OnDisconnected(IConnection connection, Exception ex)
        {
            base.OnDisconnected(connection, ex);
            Console.WriteLine(connection.RemoteEndPoint.ToString() + " disconnected");
            DZ_BatteryGrandSysteamMachineNet_Manager.middleMachineDevNet.Get_Server_Connaction_WorksNotify(connection, "DISC:" + connection.RemoteEndPoint.Address.ToString());
        }

        public override void OnException(IConnection connection, Exception ex)
        {
            base.OnException(connection, ex);
            DZ_BatteryGrandSysteamMachineNet_Manager.middleMachineDevNet.Get_Server_Connaction_WorksNotify(connection,"EXCP:" +ex.Message);
            Console.WriteLine(ex.ToString());
        }

    }
}
